package com.cssw.fyzb.tps.config.live;

import com.cssw.fyzb.tps.model.vo.CreateLiveStreamVo;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.MessageDigest;
import java.util.Calendar;
import java.util.Date;

/**
 * 腾讯直播
 *
 * @author Feng Chen
 */
@Setter
@Getter
@Component
public class TxLive {

    private static final char[] DIGITS_LOWER = {
            '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };

    /**
     * 推流地址 rtmp://domain/AppName/StreamName?txSecret=Md5(key+StreamName+hex(time))&txTime=hex(time)
     */
    @Value("${live.pushDomain}")
    private String pushDomain;

    /**
     * 拉流地址 rtmp://domain/AppName/StreamName?txSecret=Md5(key+StreamName+hex(time))&txTime=hex(time)
     */
    @Value("${live.pullDomain}")
    private String pullDomain;

    /**
     * 推流 API Key
     */
    @Value("${live.pushKey}")
    private String pushKey;

    /**
     * 拉流 API Key
     */
    @Value("${live.pullKey}")
    private String pullKey;

    @Value("${live.bizid}")
    private String bizid;

    private static final Logger logger = LoggerFactory.getLogger(TxLive.class);

    /**
     * 创建直播流
     *
     * @param appName    推流路径
     * @param streamName 推流名称
     * @param hour
     * @return
     */
    public CreateLiveStreamVo createLiveStream(String appName, String streamName, Integer hour) {
        CreateLiveStreamVo vo = new CreateLiveStreamVo();
        long txTime = txTime(hour);
        String pushUrl = getPushUrl(appName, streamName, txTime);
        String pullUrl = getPullUrl(appName, streamName, txTime);
        String accelerateUrl = getAccelerateUrl(appName, streamName, txTime);
        vo.setPushUrl(pushUrl);
        vo.setPullUrl(pullUrl);
        vo.setAccelerateUrl(accelerateUrl);
        return vo;
    }

    /**
     * 获取推流地址
     *
     * @param appName    推流路径
     * @param streamName 推流名称
     * @param txTime
     * @return
     */
    public String getPushUrl(String appName, String streamName, long txTime) {
        String str = new StringBuilder()
                .append(pushKey)
                .append(streamName)
                .append(Long.toHexString(txTime).toUpperCase())
                .toString();
        String txSecret = md5(str);
        return txSecret == null ?
                null
                :
                new StringBuilder()
                        .append("rtmp://")
                        .append(pushDomain)
                        .append("/")
                        .append(appName)
                        .append("/")
                        .append(streamName)
                        .append("?")
                        .append("txSecret=")
                        .append(txSecret)
                        .append("&")
                        .append("txTime=")
                        .append(Long.toHexString(txTime).toUpperCase())
                        .toString()
                ;
    }

    /**
     * 获取拉流地址
     *
     * @param appName
     * @param streamName
     * @param txTime
     * @return
     */
    public String getPullUrl(String appName, String streamName, long txTime) {
        String str = new StringBuilder()
                .append(pullKey)
                .append(streamName)
                .append(Long.toHexString(txTime).toUpperCase())
                .toString();
        String txSecret = md5(str);
        return txSecret == null ?
                null
                :
                new StringBuilder()
                        .append("rtmp://")
                        .append(pullDomain)
                        .append("/")
                        .append(appName)
                        .append("/")
                        .append(streamName)
                        .append("?")
                        .append("txSecret=")
                        .append(txSecret)
                        .append("&")
                        .append("txTime=")
                        .append(Long.toHexString(txTime).toUpperCase())
                        .toString()
                ;
    }


    /**
     * 获取推流地址
     *
     * @param appName    推流路径
     * @param streamName 推流名称
     * @param txTime
     * @return
     */
    public String getAccelerateUrl(String appName, String streamName, long txTime) {
        String str = new StringBuilder()
                .append(pushKey)
                .append(streamName)
                .append(Long.toHexString(txTime).toUpperCase())
                .toString();
        String txSecret = md5(str);
        return txSecret == null ?
                null
                :
                new StringBuilder()
                        .append("rtmp://")
                        .append(pullDomain)
                        .append("/")
                        .append(appName)
                        .append("/")
                        .append(streamName)
                        .append("?")
                        .append("txSecret=")
                        .append(txSecret)
                        .append("&")
                        .append("txTime=")
                        .append(Long.toHexString(txTime).toUpperCase())
                        .append("&")
                        .append("bizid=")
                        .append(bizid)
                        .toString()
                ;
    }

    // SECTION : INNER HELPER

    private static String md5(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            return hex(digest.digest(str.getBytes("UTF-8")));
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    private static String hex(byte[] data) {
        char[] out = new char[data.length << 1];
        for (int i = 0, j = 0; i < data.length; i++) {
            out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];
            out[j++] = DIGITS_LOWER[0x0F & data[i]];
        }
        return new String(out);
    }

    // SECTON : INNER HELPER

    private long txTime(Integer hour) {
        if (hour == null) {
            hour = 24;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.HOUR, hour);
        return calendar.getTimeInMillis() / 1000;
    }
}
